using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using AutoMapper;
using SapaFinance.Domain.Model;
using SapaFinance.GenericRepository;

namespace SapaFinance.Services
{
    public interface IPaymentTypeService
    {
        IEnumerable<SelectListItem> GetSelectedListById(Guid id);
        PaymentType GetPaymentType(Guid id);
        IPayerStrategy GetPayerListByPaymentTypeStrategy(Guid id);
        IPaymentTypeService RegisterPayerStrategy(string key, IPayerStrategy value);

    }

    public class PaymentTypeService : IPaymentTypeService
    {
        private readonly IMappingEngine _mappingEngine;
        private readonly IGenericRepository<PaymentType, Guid> _paymentTypeRepository;
        private readonly Dictionary<string, IPayerStrategy> _payerStrategies;
        public PaymentTypeService(IGenericRepository<PaymentType,Guid> paymentTypeRepository, IMappingEngine mappingEngine)
        {
            _paymentTypeRepository = paymentTypeRepository;
            _mappingEngine = mappingEngine;
            _payerStrategies = new Dictionary<string, IPayerStrategy>();
        }

        #region IPaymentTypeService Members
        public IPaymentTypeService RegisterPayerStrategy(string key, IPayerStrategy value)
        {
            _payerStrategies.Add(key, value);
            return this;
        }
        public IEnumerable<SelectListItem> GetSelectedListById(Guid id)
        {
            return Guid.Empty.Equals(id)
                       ? _mappingEngine.Map<IEnumerable<PaymentType>, IEnumerable<SelectListItem>>(_paymentTypeRepository.GetAll())
                       : _mappingEngine.Map<PaymentType, IEnumerable<SelectListItem>>(_paymentTypeRepository.GetById(id));
        }

        public PaymentType GetPaymentType(Guid id)
        {
            return _paymentTypeRepository.GetById(id);
        }

        public IPayerStrategy GetPayerListByPaymentTypeStrategy(Guid id)
        {
            var paymentType = GetPaymentType(id);
            var typeName = paymentType.GetType().BaseType.Name;
            var strategy = _payerStrategies.FirstOrDefault(f => f.Key.Equals(typeName));
            if (strategy.Value == null)
                throw new ArgumentException();
            return strategy.Value;
        }

        #endregion
    }

    public interface IPayerStrategy
    {
        IEnumerable<SelectListItem> GetPayerList(ICorporationService corporationService);
    }

    public class PayerListAgentNonCash : IPayerStrategy
    {
        #region IPayerStrategy Members

        public IEnumerable<SelectListItem> GetPayerList(ICorporationService corporationService)
        {
            return corporationService.GetPayerSelectedListAgentNonCash(Guid.Empty);
        }

        #endregion
    }

    public class PayerListNonCash : IPayerStrategy
    {
        #region IPayerStrategy Members

        public IEnumerable<SelectListItem> GetPayerList(ICorporationService corporationService)
        {
            return corporationService.GetPayerSelectedListNonCash(Guid.Empty);
        }

        #endregion
    }
}